#pragma once
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>

#include "user-odb.hxx"
#include "logger.hpp"

namespace im
{
    class UserTable {
    public:
        using ptr = std::shared_ptr<UserTable>;
        UserTable(const std::shared_ptr<odb::database>& db):_db(db){}

        bool insert(User& user){
            try{
                odb::transaction t(_db->begin());
                _db->persist(user);
                t.commit();
            } catch (const std::exception& e){
                LOG_CRITICAL("插入数据出错：{}",  e.what());
                return false;
            }
            return true;
        }

        bool update(User& user) {
            try{
                odb::transaction t(_db->begin());
                _db->update(user);
                t.commit();
            } catch (const std::exception& e){
                LOG_CRITICAL("更新数据出错：{}",  e.what());
                return false;
            }
            return true;
        }

        std::shared_ptr<User> select_by_nickname(const std::string &nickname) {
            std::shared_ptr<User> user;
            try {
                odb::transaction t(_db->begin());
                typedef odb::query<User> query;
                typedef odb::result<User> result;
                user.reset(_db->query_one<User>(query::nickname == nickname));
                t.commit();
            } catch (const std::exception& e){
                LOG_CRITICAL("查询数据出错：{}",  e.what());
                return user;
            }
            return user;
        }

        std::shared_ptr<User> select_by_phone(const std::string &phone) {
            std::shared_ptr<User> user;
            try{
                odb::transaction t(_db->begin());
                typedef odb::query<User> query;
                typedef odb::result<User> result;
                user.reset(_db->query_one<User>(odb::query<User>::phone == phone));
                t.commit();
            } catch (const std::exception& e){
                LOG_CRITICAL("查询数据出错：{}",  e.what());
                return user;
            }
            return user;
        }

        std::shared_ptr<User> select_by_id(const std::string &user_id) {
            std::shared_ptr<User> user;
            try{
                odb::transaction t(_db->begin());
                typedef odb::query<User> query;
                typedef odb::result<User> result;
                user.reset(_db->query_one<User>(odb::query<im::User>::user_id == user_id));
                t.commit();
            } catch (const std::exception& e){
                LOG_CRITICAL("查询数据出错：{}",  e.what());
                return user;
            }
            return user;
        }

        std::vector<User> select_multi_users(const std::vector<std::string> &id_list) {
            std::vector<User> users;
            if (id_list.empty()) {
                return users;
            }
            try{
                // 构建查询条件语句 where id in ('id1', 'id2', ...)
                std::stringstream ss;
                ss << "user_id in (";
                for (const auto &id : id_list) {
                    ss << "'" << id << "',";
                }
                std::string condition = ss.str();
                condition.pop_back();
                condition += ")";

                odb::transaction t(_db->begin());
                odb::result<User> result(_db->query<User>(odb::query<im::User>(condition)));
                
                for(auto& r : result){
                    users.push_back(r);
                }
                t.commit();
            } catch (const std::exception& e){
                LOG_CRITICAL("查询数据出错：{}",  e.what());
                return users;
            }
            return users;
        }
    private:
        std::shared_ptr<odb::database> _db;
    };
} // namespace im
